package com.jzo2o.common.utils;

import cn.hutool.json.JSON;
import cn.hutool.jwt.JWT;
import com.jzo2o.common.model.CurrentUserInfo;

import java.nio.charset.Charset;
import java.time.Duration;
import java.util.Base64;
import java.util.Date;

/**
 * JWT工具类，用于生成、解析JWT令牌及提取用户信息
 */
public class JwtTool {
    // 便于联调token有效期设置一个月 todo
    private static final Duration JWT_TOKEN_TTL = Duration.ofMinutes(24 * 60 * 30);
    // JWT负载中用户信息的key
    private static final String PAYLOAD_USER_KEY = "user";
    // 用户类型字段名
    private static final String UserType = "userType";
    // JWT签名密钥
    private byte[] key;

    /**
     * 构造方法，初始化签名密钥
     * @param keyStr 密钥字符串
     */
    public JwtTool(String keyStr) {
        key = keyStr.getBytes();
    }

    /**
     * 生成JWT令牌
     * @param currentUserId 用户ID
     * @param name 用户姓名/昵称（会进行Base64编码）
     * @param avatar 用户头像
     * @param userType 用户类型
     * @return 生成的JWT令牌
     */
    public String createToken(Long currentUserId, String name, String avatar, int userType) {
        // 姓名Base64编码，避免token令牌解析异常
        String encodeName = StringUtils.isEmpty(name) ? null : Base64Utils.encodeStr(name);
        // 构建并签名JWT，生成jws
        return JWT.create()
                .setPayload(PAYLOAD_USER_KEY, new CurrentUserInfo(currentUserId, encodeName, avatar, userType))
                .setExpiresAt(new Date(System.currentTimeMillis() + JWT_TOKEN_TTL.toMillis()))
                .setCharset(Charset.forName("UTF-8"))
                .setKey(key)
                .sign();
    }

    /**
     * 解析JWT令牌，提取用户信息
     * @param token JWT令牌
     * @return 解析后的用户信息；解析失败返回null
     */
    public CurrentUserInfo parseToken(String token) {
        try {
            // 验证并解析JWT
            JWT jwt = JWT.of(token)
                    .setKey(key);
            Object payload = jwt.getPayload(PAYLOAD_USER_KEY);
            // 复制用户信息并解码姓名
            return BeanUtils.isEmpty(payload) ? null : BeanUtils.copyBean(payload, CurrentUserInfo.class,((originObject, targetObject) -> {
                // base64解码
                if(StringUtils.isNotEmpty(targetObject.getName())) {
                    targetObject.setName(Base64Utils.decodeStr(targetObject.getName()));
                }
            }));
        } catch (Exception e) {
            // 解析异常时返回null
            return null;
        }
    }


    /**
     * 从JWT令牌中提取用户类型
     * @param token JWT令牌
     * @return 用户类型；提取失败返回null
     */
    public static Integer getUserType(String token) {
        // 解码JWT负载部分（第二部分）
        byte[] decode = Base64.getMimeDecoder().decode(token.split("\\.")[1]);
        // token明文字符串
        String tokenPlainText = new String(decode);
        // token详情字符串，截取有效JSON部分
        String tokenInfo = tokenPlainText.substring(0, tokenPlainText.lastIndexOf('}') + 1);
        JSON json = JsonUtils.parse(tokenInfo);
        JSON user = json.getByPath(PAYLOAD_USER_KEY, JSON.class);
        return user.getByPath(UserType, Integer.class);
    }

}
